package com.lizx.admin.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lizx.admin.service.DataArchivingService;
import com.lizx.admin.service.ExpenditureService;
import com.lizx.admin.service.FileService;
import com.lizx.pojo.*;
import com.lizx.pojo.vo.ExpenditureStatistics;
import com.lizx.poi.ExpenditurePOIUtils;
import com.lizx.staff.service.AreaService;
import com.lizx.staff.service.EmployeeService;
import com.lizx.staff.service.ProjectService;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

@Controller
@RequestMapping("admin/expenditure")
public class AdminExpenditureController {

    @Resource
    ExpenditureService expenditureService;
    @Resource
    FileService fileService;

    @Resource
    EmployeeService employeeService;

    @Resource
    ProjectService projectService;

    @Resource
    AreaService areaService;

    @Resource
    DataArchivingService dataArchivingService;


    @RequestMapping("list")
    public String list(){
        return "admin/expenditure/list";
    }

    @RequestMapping("getList/{start}/{end}")
    @ResponseBody
    public Map<String,Object> getList(@PathVariable int start, @PathVariable int end,@RequestBody Expenditure expenditure){
        LambdaQueryWrapper<Expenditure> queryWarpper = new LambdaQueryWrapper<Expenditure>();

        queryWarpper.eq(Expenditure::getDataArchiving,0);

        if(expenditure.getCreateTime()!=null){
            int year = expenditure.getCreateTime().getYear()+1900;
            int month = expenditure.getCreateTime().getMonth()+1;
            LocalDate today = LocalDate.of(year,month,expenditure.getCreateTime().getDate());// 获取当前日期
            queryWarpper.eq(Expenditure::getCreateTime,today);
        }
        queryWarpper.eq(StringUtils.isNotBlank(expenditure.getUname()),Expenditure::getUname,expenditure.getUname());
        queryWarpper.eq(StringUtils.isNotBlank(expenditure.getAname()),Expenditure::getAname,expenditure.getAname());
        queryWarpper.eq(StringUtils.isNotBlank(expenditure.getProjectName()),Expenditure::getProjectName,expenditure.getProjectName());
        queryWarpper.eq(StringUtils.isNotBlank(expenditure.getStatus()),Expenditure::getStatus,expenditure.getStatus());

        if(expenditure.getSearchMonth()!=null){
            int year = expenditure.getSearchMonth().getYear()+1900;
            int month = expenditure.getSearchMonth().getMonth()+1;
            LocalDate today = LocalDate.of(year,month,expenditure.getSearchMonth().getDate());// 获取当前日期
            LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 获取本月最后一天
            // ge是大于等于5月1日的数据，le是小于等于本月最后一天的数据
            queryWarpper.ge(Expenditure::getCreateTime,expenditure.getSearchMonth()).le(Expenditure::getCreateTime,lastDayOfMonth);
        }


        queryWarpper.orderByAsc(Expenditure::getStatus);
        queryWarpper.orderByDesc(Expenditure::getUpdateTime);
        queryWarpper.orderByDesc(Expenditure::getCreateTime);
        IPage<Expenditure> pagedb = new Page<Expenditure>(start,end);
        IPage<Expenditure> pageResult = expenditureService.page(pagedb, queryWarpper);
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("list",pageResult.getRecords());
        map.put("total",pageResult.getTotal());
        return map;
    }


    @RequestMapping("dataArchiving/{starDate}/{endDate}")
    @ResponseBody
    public void dataArchiving(@PathVariable("starDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date starDate,
                              @PathVariable("endDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate){


        DataArchiving dataArchiving = new DataArchiving();
        dataArchiving.setStartTime(starDate);
        dataArchiving.setEndTime(endDate);
        dataArchivingService.save(dataArchiving);

        UpdateWrapper<Expenditure> updateWrapper = new UpdateWrapper<Expenditure>();
        updateWrapper.ge("create_time",starDate);
        updateWrapper.le("create_time",endDate);
        updateWrapper.eq("status","2");
        Expenditure expenditure = new Expenditure();
        expenditure.setDataArchiving(1);
        expenditure.setDataArId(dataArchiving.getId());
        expenditureService.update(expenditure,updateWrapper);

        // 查询这个时间段的总费用
        Integer totalFee = expenditureService.sumTotalFee(starDate,endDate,2);

        dataArchiving.setTotalFee(totalFee);
        dataArchivingService.updateById(dataArchiving);
    }

        public static void main(String[] args) {
            Date d = new Date();
            System.out.println(d.getYear());
            int year = d.getYear()+1900;
            int month = d.getMonth()+1;
            LocalDate today = LocalDate.of(year,month,d.getDate());// 获取当前日期
            LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 获取本月最后一天

            System.out.println("本月最后一天的日期是: " + lastDayOfMonth);
        }

    @RequestMapping("export")
    @ResponseBody
    public void export( HttpServletResponse response,
                        @RequestParam("employeeName")String employeeName,
                        @RequestParam("projectName")String projectName,
                        @RequestParam("searchMonth")@DateTimeFormat(pattern = "yyyy-MM-dd") Date searchMonth,
                        @RequestParam("searchDate")@DateTimeFormat(pattern = "yyyy-MM-dd") Date searchDate,
                        @RequestParam("areaName")String areaName,
                        @RequestParam("status")String status){
        LambdaQueryWrapper<Expenditure> queryWarpper = new LambdaQueryWrapper<Expenditure>();



        if(searchDate!=null){
            int year = searchDate.getYear()+1900;
            int month = searchDate.getMonth()+1;
            LocalDate today = LocalDate.of(year,month,searchDate.getDate());// 获取当前日期
            queryWarpper.eq(Expenditure::getCreateTime,today);
        }
        queryWarpper.eq(StringUtils.isNotBlank(employeeName),Expenditure::getUname,employeeName);
        queryWarpper.eq(StringUtils.isNotBlank(areaName),Expenditure::getAname,areaName);
        queryWarpper.eq(StringUtils.isNotBlank(projectName),Expenditure::getProjectName,projectName);
        queryWarpper.eq(StringUtils.isNotBlank(status),Expenditure::getStatus,status);

        if(searchMonth!=null){
            int year = searchMonth.getYear()+1900;
            int month = searchMonth.getMonth()+1;
            LocalDate today = LocalDate.of(year,month,searchMonth.getDate());// 获取当前日期
            LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 获取本月最后一天
            // ge是大于等于5月1日的数据，le是小于等于本月最后一天的数据
            queryWarpper.ge(Expenditure::getCreateTime,searchMonth).le(Expenditure::getCreateTime,lastDayOfMonth);
        }
        List<Expenditure> list = expenditureService.list(queryWarpper);
        ExpenditurePOIUtils.expenditureExport(response,list);
    }

    /**
     * 支出添加或修改
     * @param expenditure
     */
    @RequestMapping("saveOrUpdate")
    @ResponseBody
    public void saveOrUpdate(@RequestBody Expenditure expenditure){
        expenditure.setDataArchiving(0);
        if(expenditure.getId()==null){
            expenditure.setStatus("2");
        }
        expenditure.setUpdateTime(new Date());
        expenditureService.saveOrUpdate(expenditure);
        LambdaQueryWrapper<File> queryWarper = new LambdaQueryWrapper<File>();
        queryWarper.eq(File::geteId,expenditure.getId());
        fileService.remove(queryWarper);
        for (String img : expenditure.getImgList()) {
            File file = new File();
            file.setFilePath(img);
            file.seteId(expenditure.getId());
            fileService.save(file);
        }
    }

    /**
     * 支出回显
     * @param id
     * @return
     */
    @RequestMapping("findById/{id}")
    @ResponseBody
    public Expenditure findById(@PathVariable int id){
        LambdaQueryWrapper<File> queryWarper = new LambdaQueryWrapper<File>();
        queryWarper.eq(File::geteId,id);
        List<File> fileList = fileService.list(queryWarper);
        List<String> imgList = fileList.stream().map(img -> img.getFilePath()).collect(Collectors.toList());
        Expenditure expenditure = expenditureService.getById(id);
        expenditure.setImgList(imgList);
        return expenditure;
    }

    /**
     * 修改状态，审核或驳回
     * @param id
     * @param status
     */
    @RequestMapping("updateStatus/{id}/{status}")
    @ResponseBody
    public void updateStatus(@PathVariable int id,@PathVariable String status){
        QueryWrapper<Expenditure> queryWarper = new QueryWrapper<Expenditure>();
        queryWarper.eq("id",id);
        Expenditure expenditure = new Expenditure();
        expenditure.setStatus(status);
        expenditure.setUpdateTime(new Date());
        expenditureService.update(expenditure,queryWarper);
    }


    /**
     * 根据支出id进行删除，实际状态更新为2
     * @param id
     */
    @RequestMapping("deleteById/{id}")
    @ResponseBody
    public void deleteById(@PathVariable int id){
        LambdaQueryWrapper<Expenditure> queryWarper = new LambdaQueryWrapper<>();
        queryWarper.eq(Expenditure::getIsdel,2);
        expenditureService.update(queryWarper);
    }


    @RequestMapping("statistics")
    public String statistics(){
        return "admin/expenditure/statistics";
    }

    /**
     * 进行支出统计
     * @return
     */
    @RequestMapping("statistics/list")
    @ResponseBody
    public List<ExpenditureStatistics> statisticsList(
//            @RequestParam("searchDate")@DateTimeFormat(pattern = "yyyy-MM-dd") Date searchDate,
            @RequestParam("areaName")String areaName,
            @RequestParam("archId")Integer archId
//            @RequestParam("archiving")Integer archiving
            ){
//        List<ExpenditureStatistics> list = expenditureService.statisticsList(searchDate,areaName,archiving);
        List<ExpenditureStatistics> list = expenditureService.statisticsList(areaName,archId);
        return list;
    }

    @RequestMapping("statistics/list/export")
    @ResponseBody
    public void export( HttpServletResponse response,
//                       @RequestParam("searchDate")@DateTimeFormat(pattern = "yyyy-MM-dd") Date searchDate,
                       @RequestParam("areaName")String areaName, @RequestParam("archId")Integer archId){
        List<ExpenditureStatistics> list = expenditureService.statisticsList(areaName, archId);
        int sumPrice = list.stream().mapToInt(expenditureStatistics->expenditureStatistics.getPrice().intValue()).sum();
        ExpenditurePOIUtils.export(response,list,sumPrice);
    }


    /**
     * 查看详情，可以查看某地区，某月份的详细列表数据
     * @param aid
     * @return
     */
    @RequestMapping("statistics/detail/{start}/{end}/{aid}/{times}")
    @ResponseBody
    public Map<String,Object> detail(@PathVariable int start, @PathVariable int end,@PathVariable Integer aid,
                                    @PathVariable @DateTimeFormat(pattern = "yyyy-MM-dd") Date times,
                                    @RequestParam("employeeName")String employeeName,
                                    @RequestParam("projectName")String projectName,
                                     @RequestParam("archiving")Integer archiving
    ){
        start = start-1; // 前台分也是1开始的
        if(start>0){
            start = start * 5; // 每页有5条，用的原生sql，limit操作的，
        }

        List<Expenditure> list = expenditureService.detail(start,end,aid,times,employeeName,projectName,archiving);
        int total = expenditureService.detailList(aid,times,employeeName,projectName).size();
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("list",list);
        map.put("total",total);
        return map;
    }


    @RequestMapping("statistics/detail/export/{aid}/{times}")
    @ResponseBody
    public void detailExport( HttpServletResponse response,
                              @PathVariable Integer aid,
                              @PathVariable @DateTimeFormat(pattern = "yyyy-MM-dd") Date times,
                              @RequestParam("employeeName")String employeeName,
                              @RequestParam("projectName")String projectName){
        List<Expenditure> list = expenditureService.detailList(aid, times,employeeName,projectName);
        int sumPrice = list.stream().mapToInt(expenditureStatistics->expenditureStatistics.getPrice().intValue()).sum();
        ExpenditurePOIUtils.detailExport(response,list,sumPrice);
    }


    @RequestMapping("downloadTemplate")
    @ResponseBody
    public void downloadTemplate( HttpServletResponse response){
        ExpenditurePOIUtils.downloadTemplate(response);
    }

    @RequestMapping("importExpenditure")
    @ResponseBody
    public Map<String,Object> importExpenditure(HttpServletRequest request,
                                    HttpServletResponse response,
                                    @RequestBody MultipartFile importExpenditureFile){
        System.out.println(importExpenditureFile.getOriginalFilename());

        List<Expenditure> list = new ArrayList<Expenditure>();

        Map<String,Object> map = new HashMap<String,Object>();
        try {
            Workbook wb = new XSSFWorkbook(importExpenditureFile.getInputStream());
            // 读取第一个Sheet
            Sheet sheetAt = wb.getSheetAt(0);
            // 总共的行数
            int rowLens = sheetAt.getLastRowNum();

            /**
             * 检查数据格式是否有问题
             */
            List<String> importMsgList = new ArrayList<String>();
            for (int rowCount = 1; rowCount <= rowLens; rowCount++) {  // 校验数据格式是否有问题
                Row row = sheetAt.getRow(rowCount);
                if (row != null) {
                    checkValue(row,rowCount,importMsgList);
                }
            }
            if(importMsgList.size()>0){ // 导入错误只展示15条错误记录
                if(importMsgList.size()>14){
                    map.put("list",importMsgList.subList(0,15));
                }else{
                    map.put("list",importMsgList);
                }
                return map;
            }
            /**
             * 得到数据，处理数据
             */
            for (int rowCount = 1; rowCount <= rowLens; rowCount++) {
                Row row = sheetAt.getRow(rowCount);
                if (row != null) {
                    Expenditure expenditure = getCellValue(row, rowCount);
                    if(expenditure!=null){
                        list.add(expenditure);
                    }
                }
            }
            // 导入的数据批量添加数据库中
            expenditureService.saveBatch(list);

            importMsgList.add("导入成功");
            map.put("list",importMsgList);
            return map;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void checkValue(Row row, int rowCount, List<String> importMsgList) {
        Expenditure expenditure = new Expenditure();

        try {
            Cell cellTime = row.getCell((short) 0);
            Date dateCellValue = cellTime.getDateCellValue();
            if(dateCellValue==null){ // 这行干什么用的，检查空数据用的
                return;
            }
            expenditure.setCreateTime(dateCellValue);
        }catch (Exception e){
            importMsgList.add("第"+rowCount+"行,第1列日期数据格式有问题");
        }

        try {
            Cell cellArea = row.getCell((short) 1);
            String areCellValue = cellArea.getStringCellValue();
            expenditure.setAname(areCellValue);

            LambdaQueryWrapper<TbArea> queryWrapper = new LambdaQueryWrapper<TbArea>();
            queryWrapper.eq(TbArea::getName,areCellValue.trim());
            List<TbArea> list = areaService.list(queryWrapper);
            if(list==null || list.size()==0){
                importMsgList.add("第"+rowCount+"行,第2列地区数据不存在");
            }
        }catch (Exception e){
            importMsgList.add("第"+rowCount+"行,第2列地区数据格式有问题");
        }
        try {
            Cell cellUname = row.getCell((short) 2);
            String unameCellValue = cellUname.getStringCellValue();
            expenditure.setUname(unameCellValue);
            LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<Employee>();
            queryWrapper.eq(Employee::getName,unameCellValue.trim());
            List<Employee> list = employeeService.list(queryWrapper);
            if(list==null  || list.size()==0){
                importMsgList.add("第"+rowCount+"行,第3列员工姓名数据不存在");
            }
        }catch (Exception e){
            importMsgList.add("第"+rowCount+"行,第3列员工姓名数据格式有问题");
        }
        try {
            Cell cellProject = row.getCell((short) 3);
            String projectCellValue = cellProject.getStringCellValue();
            expenditure.setProjectName(projectCellValue);
            LambdaQueryWrapper<TbProject> queryWrapper = new LambdaQueryWrapper<TbProject>();
            queryWrapper.eq(TbProject::getName,projectCellValue.trim());
            List<TbProject> list = projectService.list(queryWrapper);
            if(list==null  || list.size()==0){
                importMsgList.add("第"+rowCount+"行,第4列项目数据不存在");
            }
        }catch (Exception e){
            importMsgList.add("第"+rowCount+"行,第4列项目数据格式有问题");
        }
        try {
            Cell cellPrice = row.getCell((short) 4);
            double priceCellValue = cellPrice.getNumericCellValue();
            expenditure.setPrice(new BigDecimal(priceCellValue));
        }catch (Exception e){
            importMsgList.add("第"+rowCount+"行,第5列支出金额数据格式有问题");
        }
    }

    public Expenditure getCellValue(Row row,int rowCount) {
        Expenditure expenditure = new Expenditure();
        Cell cellTime = row.getCell((short) 0);
        Date dateCellValue = cellTime.getDateCellValue();
        expenditure.setCreateTime(dateCellValue);
        if(dateCellValue==null){ // 校验格式那里返回了，如果这里不做处理，就会导入很多空数据
            return null;
        }

        Cell cellArea = row.getCell((short) 1);
        String areCellValue = cellArea.getStringCellValue();
        expenditure.setAname(areCellValue);

        LambdaQueryWrapper<TbArea> queryWrapper = new LambdaQueryWrapper<TbArea>();
        queryWrapper.eq(TbArea::getName,areCellValue.trim());
        List<TbArea> list = areaService.list(queryWrapper);
        expenditure.setAid(list.get(0).getId());

        Cell cellUname = row.getCell((short) 2);
        String unameCellValue = cellUname.getStringCellValue();
        expenditure.setUname(unameCellValue);

        LambdaQueryWrapper<Employee> uqueryWrapper = new LambdaQueryWrapper<Employee>();
        uqueryWrapper.eq(Employee::getName,unameCellValue.trim());
        List<Employee> ulist = employeeService.list(uqueryWrapper);
        expenditure.setOpenid(ulist.get(0).getOpenid());

        Cell cellProject = row.getCell((short) 3);
        String projectCellValue = cellProject.getStringCellValue();
        expenditure.setProjectName(projectCellValue);

        LambdaQueryWrapper<TbProject> pqueryWrapper = new LambdaQueryWrapper<TbProject>();
        pqueryWrapper.eq(TbProject::getName,projectCellValue.trim());
        List<TbProject> plist = projectService.list(pqueryWrapper);
        expenditure.setProjectId(plist.get(0).getId());

        Cell cellPrice = row.getCell((short) 4);
        double priceCellValue = cellPrice.getNumericCellValue();
        expenditure.setPrice(new BigDecimal(priceCellValue));

        expenditure.setStatus("2"); // 导入的默认审核通过
        return expenditure;
    }



    //private static final String UPLOAD_DIR = "mydir/";
    private static final String UPLOAD_DIR = "/usr/local/mydir/financial/images/";

    @RequestMapping("uploadFile")
    @ResponseBody
    public String uploadFile(@RequestBody MultipartFile imgFile){
        System.out.println(imgFile.getOriginalFilename());

        String originalFilename = imgFile.getOriginalFilename();
        String prefix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String imgName = UUID.randomUUID().toString().replace("-","")+prefix;

        try {
            // 确保目录存在
            LocalDate currentDate = LocalDate.now();
            int year = currentDate.getYear();
            int month = currentDate.getMonthValue();
            Path uploadPath = Paths.get(UPLOAD_DIR+year+"/"+month+"/");
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }
            // 保存文件
            Path filePath = uploadPath.resolve(imgName);
            Files.copy(imgFile.getInputStream(), filePath);
            return year+"/"+month+"/"+imgName;

        } catch (IOException e) {
            e.printStackTrace();
            return "File upload failed: " + e.getMessage();
        }
    }


    @RequestMapping("batchExam")
    @ResponseBody
    public void batchExam(@RequestBody Long[] ids){
        for (Long id : ids) {
            QueryWrapper<Expenditure> queryWarper = new QueryWrapper<Expenditure>();
            queryWarper.eq("id",id);
            Expenditure expenditure = new Expenditure();
            expenditure.setStatus("2");
            expenditure.setUpdateTime(new Date());
            expenditureService.update(expenditure,queryWarper);
        }
    }

}
